package com.iflytek.cosmo.ocr.common.core.worker;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.stream.Collectors;

import com.iflytek.cosmo.ocr.common.core.BeanHelper;
import com.iflytek.cosmo.ocr.common.enums.ExportTaskStatusEnum;
import com.iflytek.cosmo.ocr.common.util.FileNameComparator;
import com.iflytek.cosmo.ocr.common.util.UUIDUtil;
import com.iflytek.cosmo.ocr.dao.OcrFileDao;
import com.iflytek.cosmo.ocr.model.domain.ExportFileInfo;
import com.iflytek.cosmo.ocr.model.entity.ExportTaskEntity;
import com.iflytek.cosmo.ocr.model.entity.OcrFileEntity;
import com.iflytek.cosmo.ocr.service.ExportTaskService;
import com.iflytek.cosmo.ocr.service.FileService;
import com.iflytek.icourt.common.util.PdfComposeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tk.mybatis.mapper.entity.Example;

/**
 * 单文件/合并导出线程
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2019/12/3 10:10
 */
public class NormalFileExportWorker implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(NormalFileExportWorker.class);





    /** 导出任务 id */
    private String taskId;

    /** 待导出的文件 id 集合 */
    private List<String> fileIds;

    /** 需要导出的文件格式 */
    private String exportFormat;

    /** 用户ID */
    private String userId;

    //需要进行转换文件的集合
    private List<String> list;

    public NormalFileExportWorker(String taskId, List<String> fileIds, String exportFormat,String userId, List<String> list) {
        this.taskId = taskId;
        this.fileIds = fileIds;
        this.exportFormat = exportFormat;
        this.userId=userId;
        this.list = list;
    }

    @Override
    public void run() {
        ExportTaskService exportTaskService = BeanHelper.getExportServiceBean();
        FileService fileService = BeanHelper.getFileService();
        OcrFileDao ocrFileDao = BeanHelper.getOcrFileDao();
        //将文件进行windows排序
        //根据id查询文件信息
        Example example = new Example(OcrFileEntity.class);
        example.createCriteria().andIn("id", fileIds);
        List<OcrFileEntity> ocrFileEntities = ocrFileDao.selectByExample(example);
        Collections.sort(ocrFileEntities, new Comparator<OcrFileEntity>() {
            private final Comparator<String> NATURAL_SORT = new FileNameComparator();
            @Override
            public int compare(OcrFileEntity ofe1, OcrFileEntity ofe2) {
                String o1 = ofe1.getFileName();
                String o2 = ofe2.getFileName();
                return NATURAL_SORT.compare(o1, o2);
            }
        });
        //获得排完序的id集合
        List<String> orderFileIds = ocrFileEntities.stream().map(OcrFileEntity::getId).collect(Collectors.toList());
        //导出文件的字节
        byte[] all_byte = null;
        //导出文件名获取
        String fileName=null;
        if (fileIds.size() == 1){
            fileName = ocrFileEntities.get(0).getFileName();
            fileName = fileName + "." + exportFormat;
        }else {
            fileName = fileService.queryDistinctDirName(fileIds);
            if(StringUtils.isEmpty(fileName)) {
                logger.info("导出文件夹不唯一！");
                return;
            }
            fileName=fileName+ "." + exportFormat;
        }
        if ("docx".equals(exportFormat) || "wps".equals(exportFormat)) {
            String orginalFormat = exportFormat;
            if ("wps".equals(exportFormat)) {
                exportFormat = "docx";
            }

            //多个word时，合成一个送入到libreoffice()
            try {
                ExportFileInfo exportFileInfo = fileService.exportToFile(orderFileIds, exportFormat);
                all_byte = exportFileInfo.getContent();
                if (ArrayUtils.isEmpty(all_byte)) {
                    throw new RuntimeException("导出word失败, 结果为0字节");
                }
            }
            catch (Exception e) {
                logger.warn("合成word异常, fileIds: {}", StringUtils.join(orderFileIds, ", "), e);
                List<String> taskIdList = new ArrayList<>();
                taskIdList.add(taskId);
                exportTaskService.delete(taskIdList);
                logger.info("上传失败，删除任务");
            }
            if (ArrayUtils.isNotEmpty(all_byte)) {
                //上传到fastdfs
                String storePath = null;
                try {
                    storePath = fileService.uploadFile(fileName, exportFormat, all_byte);
                    //根据任务的id更新路径等值
                    exportTaskService.update(taskId, ExportTaskStatusEnum.FINISHED, storePath);
                }
                catch (Exception e) {
                    if (StringUtils.isBlank(storePath)) {
                        // 如果上传失败, 删除任务
                        List<String> taskIdList = new ArrayList<>();
                        taskIdList.add(taskId);
                        exportTaskService.delete(taskIdList);
                        logger.info("上传失败，删除任务");
                    }
                    logger.warn("导出文件上传fdfs异常, fileIds: {}", StringUtils.join(orderFileIds, ", "), e);
                }
            }

        }
        else {
            if (CollectionUtils.isNotEmpty(list)) {//子任务不为空
                //非word任务，分子文件形式送入libreoffice进行识别
                for (String fileId : list) {
                    //提交执行任务，并更新path路径
                    submitTask(fileId, exportTaskService, fileService);
                }
            }
            //无限循环，直到所有子任务都完成
            Map<String, byte[]> hashmap = new HashMap<>();
            List<String> taskFileIds = new ArrayList<>();
            taskFileIds.addAll(fileIds);
            while (true) {
                //根据fileids查询所有已完成的子任务，去重，并删除未完成的子任务
                List<ExportTaskEntity> exportTaskEntities = exportTaskService
                        .findFinishTask(taskFileIds, exportFormat, ExportTaskStatusEnum.FINISHED);
                //去重后的集合
                List<ExportTaskEntity> distinctExportTaskEntities = exportTaskEntities.stream().collect(Collectors
                        .collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getFileIds()))),
                                ArrayList::new));
                //获取去重后集合的字节数组，并删除已经完成的任务
                for (ExportTaskEntity exportTaskEntity : distinctExportTaskEntities) {
                    byte[] fileBytes = fileService.getFileBytes(exportTaskEntity.getFilePath());
                    hashmap.put(exportTaskEntity.getFileIds(), fileBytes);
                    taskFileIds.remove(exportTaskEntity.getFileIds());
                }
                if (CollectionUtils.isNotEmpty(taskFileIds)) {
                    //若有未完成的任务，再次送入进行转换
                    for (String unFinishTaskId : taskFileIds) {
                        submitTask(unFinishTaskId, exportTaskService, fileService);
                    }
                }
                if (taskFileIds.size() == 0) {
                    break;
                }
            }
            //如果传过来的id只有一个，任务合成号直接返回
            if (fileIds.size() == 1) {
                return;
            }

            List<byte[]> bytes = new ArrayList<>();
            //合成任务前进行排序
            for (String fileId : orderFileIds) {
                bytes.add(hashmap.get(fileId));
            }
            String storePath = null;
            try {
                //all_byte = FileUtil.mergePDFByByte(bytes, exportFormat, fileName);
                all_byte = new PdfComposeUtil().mergePdfList(bytes);
                bytes = null;
                storePath = fileService.uploadFile(fileName, exportFormat, all_byte);
                exportTaskService.update(taskId, ExportTaskStatusEnum.FINISHED, storePath);
            }
            catch (Exception e) {
                if (StringUtils.isBlank(storePath)) {
                    // 如果上传失败, 删除任务
                    List<String> stringList = new ArrayList<>();
                    stringList.add(taskId);
                    exportTaskService.delete(stringList);
                    logger.info("上传失败，删除任务");
                }
                logger.warn("导出文件上传fdfs异常, fileIds: {}", StringUtils.join(orderFileIds, ", "), e);
            }


        }

    }

    public void submitTask(String fileId,ExportTaskService exportTaskService, FileService fileService) {
        ExportFileInfo exportFileInfo = fileService.exportToFile(fileId, exportFormat);//进行文件转换
        if (exportFileInfo == null) {
            logger.info("文件转化失败。");
            return;
        }
        byte[] fileBytes = exportFileInfo.getContent();
        String storePath = null;
        try {
            storePath = fileService.uploadFile(exportFileInfo.getFileName(), exportFormat, fileBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //查询子任务
        List<ExportTaskEntity> exportTaskEntity = exportTaskService.find(fileId, exportFormat);
        if (StringUtils.isBlank(storePath)) {
            // 如果上传失败, 删除其中一个子任务
            List<String> taskIds = new ArrayList<>();
            for (ExportTaskEntity exportTaskEntity1 : exportTaskEntity){
                taskIds.add(exportTaskEntity1.getId());
                break;
            }
            exportTaskService.delete(taskIds);
            logger.info("上传失败，删除其中一个子任务任务");
            return;
        }
        //更新子任务的字段值
        for (ExportTaskEntity exportTaskEntity1: exportTaskEntity){
            if (exportTaskEntity1.getFilePath() == null){
                exportTaskService.update(exportTaskEntity1.getId(), ExportTaskStatusEnum.FINISHED, storePath);
                break;
            }
        }

    }

    public void setSubTask(String fileId,ExportTaskService exportTaskService, OcrFileDao ocrFileDao) {
        //建立没有的子任务
        //查询文件名称
        OcrFileEntity ocrFileEntity = ocrFileDao.selectByPrimaryKey(fileId);
        if (ocrFileEntity == null){
            logger.info("文件不存在");
            return;
        }
        //不存在，则建立子任务
        ExportTaskEntity exportTaskEntity1 = new ExportTaskEntity();
        exportTaskEntity1.setId(UUIDUtil.getUUID());
        exportTaskEntity1.setCreateTime(new Date());
        exportTaskEntity1.setFileIds(fileId);
        exportTaskEntity1.setExportType(exportFormat);
        exportTaskEntity1.setStatus(ExportTaskStatusEnum.PROCESSING.toString());
        exportTaskEntity1.setFileName(ocrFileEntity.getFileName());
        exportTaskEntity1.setExporterId(userId);
        boolean b = exportTaskService.create(exportTaskEntity1);
        list.add(fileId);//不存在任务文件的集合
    }
}

